package cn.jjxx.shiro.session.mgt;

import java.io.Serializable;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Collection;
import java.util.Date;
import java.util.Map;
import java.util.Set;

import javax.servlet.http.HttpServletRequest;

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.session.Session;
import org.apache.shiro.session.UnknownSessionException;
import org.apache.shiro.session.mgt.SimpleSession;
import org.apache.shiro.session.mgt.eis.EnterpriseCacheSessionDAO;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.subject.support.DefaultSubjectContext;
import org.apache.shiro.web.session.mgt.DefaultWebSessionContext;
import org.framework.superutil.thirdparty.http.CookieUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.google.common.collect.Sets;

import cn.jjxx.core.security.shiro.session.SessionDAO;
import cn.jjxx.core.utils.DateUtils;
import cn.jjxx.core.utils.ServletUtils;
import cn.jjxx.core.utils.StringUtils;
import cn.jjxx.modules.sys.security.shiro.ShiroConstants;
import cn.jjxx.shiro.session.ShiroSession;
import cn.jjxx.shiro.session.config.RedisUtil;
import cn.jjxx.shiro.session.core.ShiroSessionConvertUtil;
import cn.jjxx.shiro.session.core.ShiroSessionRedisConstant;
import cn.jjxx.shiro.session.core.ShiroSessionRedisUtil;

public class ShiroSessionRedisDao  extends EnterpriseCacheSessionDAO   implements SessionDAO{
	private static final Logger logger = LoggerFactory.getLogger(ShiroSessionListener.class);
	@Override
	protected Serializable doCreate(Session session) {
		Serializable sessionId = super.doCreate(session);
		RedisUtil.setObject(ShiroSessionRedisConstant.SHIROSESSION_REDIS_DB,
				(ShiroSessionRedisConstant.SHIROSESSION_REDIS_PREFIX+sessionId.toString()).getBytes(),
				ShiroSessionConvertUtil.sessionToByte(session),ShiroSessionRedisConstant.SHIROSESSION_REDIS_EXTIRETIME);
		 
		ShiroSessionRedisUtil.setSSOCreateSession(session);
		return sessionId;
	}


	@Override
	public Session readSession(Serializable sessionId) throws UnknownSessionException {
		return this.doReadSession(sessionId);
	}

	@Override
	protected Session doReadSession(Serializable sessionId) {
		Session session = null;
		try { 
			HttpServletRequest request = ServletUtils.getRequest();
		 
			byte[] bytes = RedisUtil.getObject(ShiroSessionRedisConstant.SHIROSESSION_REDIS_DB,
					(ShiroSessionRedisConstant.SHIROSESSION_REDIS_PREFIX+sessionId.toString()).getBytes(),
					ShiroSessionRedisConstant.SHIROSESSION_REDIS_EXTIRETIME);
			if(bytes != null && bytes.length > 0){
				
				session = ShiroSessionConvertUtil.byteToSession(bytes);
				ShiroSessionRedisUtil.setSSOCreateSession(session);
				request.setAttribute("session_" + sessionId, session);   
			} 
		} catch (Exception e) {
			 
		}
		return session;
	}

	@Override
	protected void doUpdate(Session session) {
		super.doUpdate(session);
		RedisUtil.updateObject(ShiroSessionRedisConstant.SHIROSESSION_REDIS_DB,
				(ShiroSessionRedisConstant.SHIROSESSION_REDIS_PREFIX+session.getId().toString()).getBytes(),
				ShiroSessionConvertUtil.sessionToByte(session),
				ShiroSessionRedisConstant.SHIROSESSION_REDIS_EXTIRETIME);
		ShiroSessionRedisUtil.setSSOCreateSession(session);
		
		
		//也要更新token
		/*User user = (User)session.getAttribute(Const.SESSION_USER);
		if(null != user){
			RedisUtil.updateString(SHIROSESSION_REDIS_DB,ShiroSessionRedisConstant.SSOTOKEN_REDIS_PREFIX+user.getUSERNAME(),ShiroSessionRedisConstant.SHIROSESSION_REDIS_EXTIRETIME);
		}*/ 
	}

	@Override
	protected void doDelete(Session session) {
		super.doDelete(session);
		RedisUtil.delString(ShiroSessionRedisConstant.SHIROSESSION_REDIS_DB,
				ShiroSessionRedisConstant.SHIROSESSION_REDIS_PREFIX+session.getId().toString());
		
		RedisUtil.delString(ShiroSessionRedisConstant.SHIROSESSION_REDIS_DB,
				ShiroSessionRedisConstant.MAIN_SYSTEM_TOKEN);
		
		
		RedisUtil.delString(ShiroSessionRedisConstant.SHIROSESSION_REDIS_DB,
				ShiroConstants.ONLINE_SESSION+session.getId()); 
		
		//也要删除token
		/*User user = (User)session.getAttribute(Const.SESSION_USER);
		if(null != user){
			RedisUtil.delString(SHIROSESSION_REDIS_DB,ShiroSessionRedisConstant.SSOTOKEN_REDIS_PREFIX+user.getUSERNAME());
		}*/
	}


	@Override
	public Collection<Session> getActiveSessions(boolean includeLeave) {
		return getActiveSessions(includeLeave,null,null);
	}


	@Override
	public Collection<Session> getActiveSessions(boolean includeLeave, Object principal, Session filterSession) {
		Set<Session> sessions = Sets.newHashSet(); 
		try { 
			Session session = new SimpleSession();
			/*// 符合登陆者条件。
			PrincipalCollection pc = (PrincipalCollection) session.getAttribute(DefaultSubjectContext.PRINCIPALS_SESSION_KEY);
			
			if (pc != null) {
				if (principal.toString().equals(pc != null ? pc.getPrimaryPrincipal().toString() : StringUtils.EMPTY)) {
					if (filterSession != null && filterSession.getId().equals(session.getId())) {
						session = ShiroSessionRedisUtil.getSession(session.getId());
						sessions.add(session);
						//doUpdate(session);
					}
				}
			} */
			if (!includeLeave) {
				Set<String> keys = RedisUtil.keysLike(ShiroSessionRedisConstant.SHIROSESSION_REDIS_DB, ShiroConstants.ONLINE_SESSION + "*");
				for (String string : keys) {
					byte[] bytes = RedisUtil.getObject(ShiroSessionRedisConstant.SHIROSESSION_REDIS_DB,
							(string).getBytes(),
							ShiroSessionRedisConstant.SHIROSESSION_REDIS_EXTIRETIME);
					if (bytes != null && bytes.length > 0) {
						session = (ShiroSession) ShiroSessionConvertUtil.byteToObejct(bytes);
						DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
						Date lasttime = session.getLastAccessTime();
						Date currtime = new Date();
						long retTime = cn.jjxx.shiro.session.RedisUtil.getLastvalue(df.format(currtime), df.format(lasttime));
						if (retTime < 30) {
							sessions.add(session);
						} else {
							RedisUtil.delString(ShiroSessionRedisConstant.SHIROSESSION_REDIS_DB,
									ShiroSessionRedisConstant.SHIROSESSION_REDIS_PREFIX + string.replace("SSO:online:online_session-", ""));
							RedisUtil.delString(ShiroSessionRedisConstant.SHIROSESSION_REDIS_DB,string);
						}
					}
				}
			}
			logger.info("getActiveSessions size: {} ", sessions.size());
		} catch (Exception e) {
			logger.error("getActiveSessions", e); 
		} finally { 
		}
		return sessions;
	}
}